/*************************************************************
Date: 2010-12
Description: 数据结构定义
***********************************************************/
#ifndef __COMMON_DEFINE_H__
#define __COMMON_DEFINE_H__
namespace ssdasn {
//最大数据包大小
#define MAX_PACKET_SIZE		(10*1024*1024)
#define MAX_LIST_SIZE 256
#define MAX_ENCODE_LIST_SIZE 512
#define LATEST_STATICS_INTERVAL 6
#define LEAST_REQ_CNT_TO_FREEZE 6
#define CONNECTION_ALIVE_DETECT 30

//每隔5分钟清理一次不处于连接状态的L5路由
#define CLEAN_SVR_INTERVAL 300
//5分钟没有请求的连接认为是断开了
#define CONNECT_ALIVE_INTERVAL 300

//默认缓冲大小
#define DEFAULT_BUFF_SIZE  (1024)
enum cache_op{
	cache_op_set	= 0,
	cache_op_del	= 1,
	cache_op_get	= 2,
	cache_op_setlist= 3,
	cache_op_dellist= 4,
	cache_op_getlist= 5,
	cache_op_set_v2	= 6,
	cache_op_del_v2	= 7,
	cache_op_get_v2	= 8,
	cache_op_setlist_v2 = 9,
	cache_op_dellist_v2 = 10,
	cache_op_getlist_v2 = 11,
	cache_op_set_col	= 12,
	cache_op_del_col	= 13,
	cache_op_get_col	= 14,
	cache_op_set_mul_col = 15,
	cache_op_del_mul_col = 16,
	cache_op_get_mul_col = 17,
	cache_op_set_v2_1 = 18,
	cache_op_setlist_v2_1 = 19,
	cache_op_add = 20,
	cache_op_replace = 21,
	cache_op_incr = 22,
	cache_op_decr = 23,
	cache_op_invalid,
};

enum cache_errno{
	cache_err_base		= -11900,
	cache_err_illegal	= cache_err_base,
	cache_err_encode	= cache_err_base - 1,
	cache_err_decode	= cache_err_base - 2,
	cache_err_bad_pkt	= cache_err_base - 3,
	cache_err_bad_choice= cache_err_base - 4,
	cache_err_connect	= cache_err_base - 5,
	cache_err_send		= cache_err_base - 6,
	cache_err_recv		= cache_err_base - 7,
	err_seq_dismatch 	= cache_err_base - 8,
	err_packet_too_big	= cache_err_base - 9,
	err_invalid_col	= cache_err_base - 10,
	err_empty_req =  cache_err_base - 11,
	err_internal_trans =  cache_err_base - 12,
	err_args = cache_err_base - 13,
	err_list_too_long = cache_err_base - 14, /*> 256*/
	err_read_timeout = cache_err_base - 15,
	err_incr_value_decode = cache_err_base - 16,
	err_l5 = cache_err_base - 17,
	err_invalid_passwd = cache_err_base -18,
};

// client_flag用于标识客户端特征，如使用L5，使用密码
// 需要与access 定义保持一致
enum client_flag{
	em_cli_flg_use_passwd 	= 1<<0,
	em_cli_flg_use_l5 		= 1<<1,
};



typedef struct{
	string key;
	string data;
	int retcode;
}TKeyNode;


enum host_state{
	HOST_AVAILABLE,
	HOST_UNAVAILABLE,
};

enum opstr_tag {
	OPSTR_TAG_LOCAL_PARSE = 1,
	OPSTR_TAG_SO_PARSE = 2,
	OPSTR_TAG_MEMCACHED_REPLACE = 11,
	OPSTR_TAG_MEMCACHED_ADD = 12,
	OPSTR_TAG_MEMCACHED_INCR = 16,
	OPSTR_TAG_MEMCACHED_DECR = 17,
};


typedef struct TServerAddr
{
	TServerAddr(){
		memset(strIP, 0, sizeof(strIP));
		usPort = 0;
	}
	char strIP[20];
	unsigned short usPort;
}TServerAddr;

typedef struct THostCtrl
{
	THostCtrl(){
		uiIP = 0;
		usPort = 0;
		state = HOST_AVAILABLE;
		sock_fd = -1;
		last_freeze_time = (time_t) 0;
		statistics = 0;
		latest_statics_time = 0;
		latest_request_cnt = 0;
		latest_read_timeout_cnt = 0;
		last_request_time = 0;
		strErr[0] = '\0';
	}
	unsigned int uiIP;
	unsigned short usPort;

	unsigned char state;
	int sock_fd;
	time_t last_freeze_time;
	unsigned long long statistics; //连接建立后发送请求次数统计
	int latest_statics_time; //最近60s统计开始时间
	int latest_request_cnt;//最近60s开始到现在的请求个数
	int latest_read_timeout_cnt;//最近60s开始到现在的读超时个数
	int last_request_time;//最近一次发包时间
	char strErr[512]; // add by cjhuang
	void reset_latest_statics(int now)
	{
		latest_statics_time = now;
		latest_request_cnt = 0;
		latest_read_timeout_cnt = 0;
	}
}THostCtrl;


/*--------------------------------v2 version add--------------*/
/*
* 各个参数含义请参考set_v2,get_v2,del_v2
* 对于不v2单个操作不需要的参数将被忽略
* 请求有效参数:
* setlist_v2: key, data, cas, expire, offset, len
* getlist_v2: key, offset, len
* dellist_v2: key, cas
* 答复结果:
* setlist_v2: key, retcode, cas
* getlist_v2: key, retcode, data, cas
* dellist_v2: key, retcode
*/
struct TKeyNodeV2
{
	TKeyNodeV2():key(""),
		data(""),
		retcode(-1),
		cas(-1),
		expire(0),
		offset(0),
		len(-1)
	{
	}
	
	string key;
	string data;
	int retcode;
	int cas; //setlist不使用cas填-1,setlist和getlist会返回最新的结果在这里，如果为-1则是无效值
	int expire;//永不超时填0或负值，其他为超时的秒数
	int offset;//数据操作的起始偏移，默认是0
	int len;//数据操作的长度，-1表示到结尾
};
/*用于扩展返回结果*/
typedef struct TRspExt
{
	TRspExt() : expire(0), len(-1)
	{
	}
	
	int expire;//超时绝对时间
	int len; //返回set、append操作后，value的长度
	string strEchoValue;// 返回set、append操作后，value的值；失败则返回set的值(最长4K)
}TRspExt;
/*用于扩展传入参数*/
typedef struct TReqExt
{
	TReqExt() : col(0)
	{
		
		passwd = 0;
		clientflg = 0;
	}

	unsigned int col;//列号0~511
	unsigned int passwd;
	unsigned int clientflg; 
}TReqExt;
/*--------------------------------column version add--------------*/

typedef struct TSetNode
{
	TSetNode(): col(0),
		data(""),
		retcode(-1)
	{
	}
	
	unsigned int col;//列号，从0开始,最大是511
	string data;//set时表示要设置的数据
	int retcode;//返回码,0表示成功，其他表示失败
}TSetNode;

typedef struct TGetNode
{
	TGetNode():  col(0),
		data(""),
		retcode(-1)
	{
	}
	
	unsigned int col;//列号，从0开始,最大是511
	string data;//get结果 
	int retcode;//返回码,0表示成功，其他表示失败
}TGetNode;

typedef struct TDelNode
{
	TDelNode():  col(0),
		retcode(-1)
	{
	}
	
	unsigned int col;//列号，从0开始,最大是511
	int retcode;//返回码,0表示成功，其他表示失败
}TDelNode;

typedef struct TKeySetListNode
{
	TKeySetListNode(): key(""),
		cas(-1),
		v_col_node(0),
		retcode(-1)
	{
	}
	
	string key;//key
	int cas;	// -1表示不使用
	vector< TSetNode > v_col_node;//列数组
	int retcode;//0 全部成功,> 0  retcode!=0的个数, <0 表示接口错误，即其他错误码
}TKeySetListNode;

typedef struct TKeyGetListNode
{
	TKeyGetListNode(): key(""),
		cas(-1),
		v_col_node(0),
		retcode(-1)
	{
	}
	
	string key;//key
	int cas;	// -1表示不使用，用于返回cas
	vector< TGetNode > v_col_node;//列数组
	int retcode;//0 全部成功,> 0  retcode!=0的个数, <0 表示接口错误，即其他错误码
 }TKeyGetListNode;

typedef struct TKeyDelListNode
{
	TKeyDelListNode(): key(""),
		cas(-1),
		v_col_node(0),
		retcode(-1)
	{
	}
	
	string key;//key
	int cas;	// -1表示不使用
	vector< TDelNode > v_col_node;//列数组
	int retcode;//0 全部成功,> 0  retcode!=0的个数, <0 表示接口错误，即其他错误码
}TKeyDelListNode;

typedef struct TKeyNodeInternal
{
	TKeyNodeInternal():key(""),
		data(""),
		retcode(-1),
		cas(-1),
		expire(0),
		offset(0),
		len(-1),
		col(-1)
	{
	
	}
	
	string key;
	string data;
	int retcode;
	int cas; //setlist不使用cas填-1,setlist和getlist会返回最新的结果在这里，如果为-1则是无效值
	int expire;//永不超时填0或负值，其他为超时的秒数
	int offset;//数据操作的起始偏移，默认是0
	int len;//数据操作的长度，-1表示到结尾
	int col; //0~255
}TKeyNodeInternal;
#if 0
#define DEBUG_DUMP(...)  xdump(__VA_ARGS__)
#define DEBUG_PRINT(...)  printf(__VA_ARGS__)
#else
#define DEBUG_DUMP(...)
#define DEBUG_PRINT(...)
#endif

//使用api拿到统计信息，直接调用ToString即可转换为可读的字符串
typedef struct TStatistics
{
	//导出为字符串
	void ToString(string &s)
	{
		char buf[256];
		map<int, long long>::iterator it;
		s.append("mapSet-------\n");
		for(it = mapSet.begin(); it != mapSet.end(); ++it)
		{
			snprintf(buf, sizeof(buf), "%d %lld\n", it->first, it->second);
			s.append(buf);
		}
		s.append("mapGet-------\n");
		for(it = mapGet.begin(); it != mapGet.end(); ++it)
		{
			snprintf(buf, sizeof(buf), "%d %lld\n", it->first, it->second);
			s.append(buf);
		}
		s.append("mapDel-------\n");
		for(it = mapDel.begin(); it != mapDel.end(); ++it)
		{
			snprintf(buf, sizeof(buf), "%d %lld\n", it->first, it->second);
			s.append(buf);
		}
		s.append("mapSys-------\n");
		for(it = mapSys.begin(); it != mapSys.end(); ++it)
		{
			snprintf(buf, sizeof(buf), "%d %lld\n", it->first, it->second);
			s.append(buf);
		}
	}
	void IncSet(int iRetCode, int iCount = 1)
	{
		if(mapSet.find(iRetCode) != mapSet.end())
			mapSet[iRetCode] += iCount;
		else
			mapSet[iRetCode] = iCount;
	}
	void ClearSet()
	{
		mapSet.clear();
	}
	void IncGet(int iRetCode, int iCount = 1)
	{
		if(mapGet.find(iRetCode) != mapGet.end())
			mapGet[iRetCode] += iCount;
		else
			mapGet[iRetCode] = iCount;
	}
	void ClearGet()
	{
		mapGet.clear();
	}
	void IncDel(int iRetCode, int iCount = 1)
	{
		if(mapDel.find(iRetCode) != mapDel.end())
			mapDel[iRetCode] += iCount;
		else
			mapDel[iRetCode] = iCount;
	}
	void ClearDel()
	{
		mapDel.clear();
	}
	void IncSys(int iRetCode, int iCount = 1)
	{
		if(mapSys.find(iRetCode) != mapSys.end())
			mapSys[iRetCode] += iCount;
		else
			mapSys[iRetCode] = iCount;
	}
	void ClearSys()
	{
		mapSys.clear();
	}
	void ClearAll()
	{
		mapSet.clear();
		mapGet.clear();
		mapDel.clear();
		mapSys.clear();
	}
	//每种返回值的计数	,批量的统计子操作
	map<int, long long> mapSet; 
	map<int, long long> mapGet;
	map<int, long long> mapDel; 
	map<int, long long> mapSys;//系统错误码
}TStatistics;
}
#endif //__COMMON_DEFINE_H__

